import numpy as np 
bn_param = {'running_mean':0, 'running_var':0, 'momentum':0.99, 'eps': 0.000001}
def Batchnorm_simple_for_train(x, gamma, beta, bn_param):
    ''' 
    param:x    : 输入数据，设shape(B,L)
    param:gama : 缩放因子  γ
    param:beta : 平移因子  β
    param:bn_param   : batchnorm所需要的一些参数
        eps      : 接近0的数，防止分母出现0
        momentum : 动量参数，一般为0.9， 0.99， 0.999
        running_mean ：滑动平均的方式计算新的均值，训练时计算，为测试数据做准备
        running_var  : 滑动平均的方式计算新的方差，训练时计算，为测试数据做准备
    '''
    running_mean = bn_param['running_mean']  #shape = [B]
    running_var = bn_param['running_var']    #shape = [B]
    eps = bn_param['eps']
    momentum = bn_param['momentum']
    results = 0. # 建立一个新的变量
    
    x_mean=x.mean(axis=0)  # 计算x的均值
    x_var=x.var(axis=0)    # 计算方差
    x_normalized=(x-x_mean)/np.sqrt(x_var+eps)       # 归一化
    results = gamma * x_normalized + beta            # 缩放平移
 
    running_mean = momentum * running_mean + (1 - momentum) * x_mean
    running_var = momentum * running_var + (1 - momentum) * x_var
    
    #记录新的值
    bn_param['running_mean'] = running_mean
    bn_param['running_var'] = running_var 
    
    return results , bn_param

def Batchnorm_simple_for_test(x, gamma, beta, bn_param):
    """
    param:x    : 输入数据，设shape(B,L)
    param:gama : 缩放因子  γ
    param:beta : 平移因子  β
    param:bn_param   : batchnorm所需要的一些参数
        eps      : 接近0的数，防止分母出现0
        momentum : 动量参数，一般为0.9， 0.99， 0.999
        running_mean ：滑动平均的方式计算新的均值，训练时计算，为测试数据做准备
        running_var  : 滑动平均的方式计算新的方差，训练时计算，为测试数据做准备
    """
    running_mean = bn_param['running_mean']  #shape = [B]
    running_var = bn_param['running_var']    #shape = [B]
    eps = bn_param['eps']
    results = 0. # 建立一个新的变量
   
    x_normalized=(x-running_mean )/np.sqrt(running_var +eps)       # 归一化
    results = gamma * x_normalized + beta            # 缩放平移
    
    return results , bn_param

# def __init__(self, num_classes, pretrained=False,
#               bn_after_act=False, bn_before_act=False):
#     super(Vgg19, self).__init__()
 
#     self.pretrained = pretrained
#     self.bn_before_act = bn_before_act
#     self.bn_after_act = bn_after_act
 
#     model = models.vgg19(pretrained = pretrained)
#     self.features = model.features
       
#     self.fc17 = nn.Linear(512 * 7 * 7, 4096)
#     self.bn17 = nn.BatchNorm1d(4096)
#     self.fc18 = nn.Linear(4096, 4096)
#     self.bn18 = nn.BatchNorm1d(4096)
#     self.fc19 = nn.Linear(4096, num_classes)
 
#     self._initialize_weights()